<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>socket test</title>
    <script src="jquery-3.6.0.slim.min.js"></script>
</head>
<body>
<style>
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
    }

    #app {
        margin: 20px;
    }

    #main {
        height: 800px;
        margin-top: 20px;
        margin-bottom: 20px;
    }

    #history {
        width: 70%;
        height: 800px;
        border: black solid 1px;
        float: left;
        overflow-y: auto;
        word-wrap: break-word
    }

    #clientListShowArea {
        width: 30%;
        height: 800px;
        padding-left: 10px;
        float: left;
        border: black solid 1px;
        overflow-y: auto;
    }

    #serverAddress, #sendDataContent {
        width: 500px;
    }

    #autoSendTime {
        width: 50px;
    }

</style>
<div id="app">
    <button id="switchTcpServer">OpenTcpServer</button>
    <input id="serverAddress" disabled/>
    <button id="clearWindow">clearWindow</button>
    <span id="clientCountArea">current client count:0</span>
    <button id="saveCurrentServerLog">saveCurrentServerLog</button>
    <div id="main">
        <div>
            <div id="history"></div>
        </div>
        <div id="clientListShowArea">

        </div>
    </div>
    <input type="text" id="sendDataContent">
    <button id="sendDataButton" disabled>send</button>
    <input id="uploadFile" type="file"/>
    <button id="sendFileButton" disabled>send file</button>
    <button id="switchHex">switch to hex mode</button>
    <button id="switchAutoSend" disabled>start auto send</button>
    <input type="text" id="autoSendTime">ms
</div>
<script>
    let hexToString = function (hex) {
        let arr = hex.split("")
        let out = ""
        for (let i = 0; i < Math.floor(arr.length / 2); i++) {
            let tmp = "0x" + arr[i * 2] + arr[i * 2 + 1]
            let charValue = String.fromCharCode(tmp);
            out += charValue
        }
        return out
    };

    let stringToHex = function (str) {
        let val = "";
        for (let i = 0; i < str.length; i++) {
            if (val === "")
                val = str.charCodeAt(i).toString(16);
            else
                val += str.charCodeAt(i).toString(16);
        }
        return val
    }
    let objIsEmpty = (obj) => (JSON.stringify(obj) === '{}')
    let switchTcpServerFun = function () {
        if (!connected) {
            websocket.send("OpenTcpServer")
        } else {
            clientCount = 0
            noClient = true
            clientCountArea.text(`current client count:${clientCount}`)
            websocket.send("CloseTcpServer")
            clientListShowArea.html("")
            history.html("")
            clientMap = {}
            connected = false
            switchTcpServerButton.text("OpenTcpServer")
            serverAddressInput.attr("value", "")
            sendDataButton.attr("disabled", "")
            sendFileButton.attr("disabled", "")
            switchAutoSend.attr("disabled", "")
            autoSend = false
            switchAutoSend.text("start auto send")
        }
    }
    let clientCount = 0
    let noClient = true
    let clientMap = {}
    let currentClientID = ""
    let currentClientName = ""
    let timerID = 0
    let serverPort = 0
    let websocket = null
    let connected = false
    let autoSend = false
    let hexMode = false
    let uploadFile = $("#uploadFile")
    let switchTcpServerButton = $("#switchTcpServer")
    let serverAddressInput = $("#serverAddress")
    let clearWindow = $("#clearWindow")
    let saveCurrentServerLog = $("#saveCurrentServerLog")
    let history = $("#history")
    let sendDataContent = $("#sendDataContent")
    let sendDataButton = $("#sendDataButton")
    let sendFileButton = $("#sendFileButton")
    let switchHex = $("#switchHex")
    let switchAutoSend = $("#switchAutoSend")
    let autoSendTime = $("#autoSendTime")
    let clientListShowArea = $("#clientListShowArea")
    let clientCountArea = $("#clientCountArea")
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://airtest.openluat.com:2900/socket");
        websocket.onopen = function () {
            switchTcpServerFun()
            clientCount = 0
        }
        websocket.onmessage = function (event) {
            let webSocketEvent = JSON.parse(event.data)
            if (webSocketEvent.event === "openTcpServerPort") {
                serverPort = webSocketEvent.port
                if (serverPort !== 0) {
                    connected = true
                    switchTcpServerButton.text("CloseTcpServer")
                    serverAddressInput.attr("value", `tcp://airtest.openluat.com:${serverPort}`)
                    sendDataButton.attr("disabled", false)
                    sendFileButton.attr("disabled", false)
                    switchAutoSend.attr("disabled", false)
                }
                return
            }
            let clientInfo = webSocketEvent.clientInfo.ip + ":" + webSocketEvent.clientInfo.port
            let clientInfoFormat = clientInfo.replaceAll(".", "")
            clientInfoFormat = clientInfoFormat.replace(":", "")
            if (webSocketEvent.event === "clientMsg") {
                let date = new Date().toLocaleString();
                clientMap[clientInfoFormat]["msgList"].push({
                    "type": "receive",
                    "time": date,
                    "data": webSocketEvent.data
                })
                if (clientMap[clientInfoFormat]["selected"] === true) {
                    history.append(`<p>【${date}】(${clientInfo}) receive->【${webSocketEvent.data.length}bytes】${webSocketEvent.data}</p><hr>`)
                    let historyTmp = document.getElementById('history')
                    historyTmp.scrollTop = historyTmp.scrollHeight
                }
            } else if (webSocketEvent.event === "clientConnect") {
                clientCount++;
                clientCountArea.text(`current client count:${clientCount}`)
                if (noClient) {
                    clientListShowArea.append("<div id=" + clientInfoFormat + " style='text-align: center; line-height: 50px; height: 50px; border: black solid 1px; margin: 10px; cursor: pointer; background-color: yellow'>" + clientInfo + "</div>")
                    clientMap[clientInfoFormat] = {
                        "selected": true,
                        "msgList": []
                    }
                    noClient = false
                    currentClientID = clientInfoFormat
                    currentClientName = clientInfo
                } else {
                    clientListShowArea.append("<div id=" + clientInfoFormat + " style='text-align: center; line-height: 50px; height: 50px; border: black solid 1px; margin: 10px; cursor: pointer'>" + clientInfo + "</div>")
                    clientMap[clientInfoFormat] = {
                        "selected": false,
                        "msgList": []
                    }
                }
            } else if (webSocketEvent.event === "clientDisConnect") {
                clientCount--
                if (clientCount < 0) {
                    clientCount = 0
                }
                clientCountArea.text(`current client count:${clientCount}`)
                let children = clientListShowArea.children()
                for (let i = 0; i < children.length; i++) {
                    if (children[i].innerText === clientInfo) {
                        children[i].remove()
                        break
                    }
                }
                children = clientListShowArea.children()

                if (clientInfoFormat === currentClientID) {
                    history.html("")
                }

                if (children.length > 0) {
                    let willBeSelectClient = $(children[0])
                    willBeSelectClient.css("background-color", "yellow")
                    currentClientID = willBeSelectClient.attr("id")
                    currentClientName = willBeSelectClient.text()
                    clientMap[currentClientID]["selected"] = true
                    let willShowHistory = clientMap[currentClientID]["msgList"]
                    for (let willShowMsgkey in willShowHistory) {
                        if (willShowHistory[willShowMsgkey].type === "receive") {
                            history.append(`<p>【${willShowHistory[willShowMsgkey].time}】(${currentClientName}) receive->【${willShowHistory[willShowMsgkey].data.length}bytes】${willShowHistory[willShowMsgkey].data}</p><hr>`)
                        } else {
                            history.append(`<p>【${willShowHistory[willShowMsgkey].time}】(${currentClientName}) <-send【${willShowHistory[willShowMsgkey].data.length}bytes】${willShowHistory[willShowMsgkey].data}</p><hr>`)
                        }
                        let historyTmp = document.getElementById('history')
                        historyTmp.scrollTop = historyTmp.scrollHeight
                    }
                } else {
                    currentClientName = ""
                    currentClientID = ""
                }
                delete clientMap[clientInfoFormat]
                if (objIsEmpty(clientMap)) {
                    noClient = true
                }
            } else {
                console.log("webSocket port" + webSocketEvent)
            }
        }
        websocket.onclose = function () {
            clientCount = 0
            clientCountArea.text(`current client count:${clientCount}`)
            websocket.send("CloseTcpServer")
            clientListShowArea.html("")
            connected = false
            switchTcpServerButton.text("OpenTcpServer")
            serverAddressInput.attr("value", "")
            sendDataButton.attr("disabled", "")
            sendFileButton.attr("disabled", "")
            switchAutoSend.attr("disabled", "")
            autoSend = false
            switchAutoSend.text("start auto send")
            history.html("")
        }
        websocket.onerror = function () {
        }
        window.onbeforeunload = function () {

        }
    } else {
        alert('当前浏览器不支持websocket')
    }
    clientListShowArea.on("click", "div", function () {
        if (!autoSend) {
            $("#clientListShowArea div").css("background-color", "white")
            $(this).css("background-color", "yellow")
            currentClientID = $(this).attr("id")
            currentClientName = $(this).text()
            history.html("")
            for (let clientMapKey in clientMap) {
                clientMap[clientMapKey].selected = false
            }
            clientMap[currentClientID]["selected"] = true
            let willShowHistory = clientMap[currentClientID]["msgList"]
            for (let willShowMsgkey in willShowHistory) {
                if (willShowHistory[willShowMsgkey].type === "receive") {
                    history.append(`<p>【${willShowHistory[willShowMsgkey].time}】(${currentClientName}) receive->【${willShowHistory[willShowMsgkey].data.length}bytes】${willShowHistory[willShowMsgkey].data}</p><hr>`)
                } else {
                    history.append(`<p>【${willShowHistory[willShowMsgkey].time}】(${currentClientName}) <-send【${willShowHistory[willShowMsgkey].data.length}bytes】${willShowHistory[willShowMsgkey].data}</p><hr>`)
                }
                let historyTmp = document.getElementById('history')
                historyTmp.scrollTop = historyTmp.scrollHeight
            }
        }

    })
    clearWindow.click(
        function () {
            history.html("")
            clientMap[currentClientID]["msgList"] = []
        }
    )
    switchTcpServerButton.click(
        function () {
            switchTcpServerFun()
        }
    )
    saveCurrentServerLog.click(
        function () {
            let $a = document.createElement('a');
            $a.setAttribute("href", "http://airtest.openluat.com:2900/download/" + serverPort + ".txt");
            $a.setAttribute("download", "");

            let evObj = document.createEvent('MouseEvents');
            evObj.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, true, false, 0, null);
            $a.dispatchEvent(evObj);
        }
    )

    sendDataButton.click(
        function () {
            let value = sendDataContent.val()
            if (!noClient && value !== "") {
                websocket.send(JSON.stringify({
                    "isHex": hexMode.toString(),
                    "data": value,
                    "event": "serverMsg",
                    "client": currentClientName
                }))
            }
            let date = new Date().toLocaleString();
            clientMap[currentClientID]["msgList"].push({
                "isHex": hexMode.toString(),
                "type": "send",
                "time": date,
                "data": value
            })
            if (hexMode) {
                history.append(`<p>【${date}】(${currentClientName}) <-send hex【${value.length}bytes】0x${value}</p><hr>`)
            } else {
                history.append(`<p>【${date}】(${currentClientName}) <-send【${value.length}bytes】${value}</p><hr>`)
            }
            let historyTmp = document.getElementById('history')
            historyTmp.scrollTop = historyTmp.scrollHeight
        }
    )

    sendFileButton.click(
        function () {
            sendFileButton.attr("disabled", false)
            let willUploadFile = uploadFile[0].files[0]
            if (willUploadFile === undefined) {
            } else {
                let my_fr = new FileReader()
                my_fr.readAsText(willUploadFile)
                my_fr.onload = function () {
                    let fileContent = my_fr.result
                    let start = 0
                    let size = 1024
                    while (true) {
                        let dataTmp = my_fr.result.substring(start, start + size)
                        if (dataTmp === "") {
                            sendFileButton.attr("disabled", false)
                            break
                        }
                        websocket.send(JSON.stringify({
                                "isHex": hexMode.toString(),
                                "data": dataTmp,
                                "event": "serverMsg",
                                "client": currentClientName
                            })
                        )
                        start += size
                    }
                }
            }
        }
    )

    switchHex.click(
        function () {
            if (hexMode === true) {
                hexMode = false
                switchHex.text("switch to hex mode")
            } else {
                hexMode = true
                switchHex.text("switch to normal mode")
            }
        }
    )

    switchAutoSend.click(
        function () {
            if (autoSend) {
                autoSend = false
                sendDataButton.attr("disabled", false)
                sendFileButton.attr("disabled", false)
                switchHex.attr("disabled", false)
                clearInterval(timerID)
                switchAutoSend.text("start auto send")
            } else {
                let loopTime = autoSendTime.val()
                let parseLoopTime = parseInt(autoSendTime.val())
                if (loopTime !== "" && parseLoopTime > 0 && !noClient) {
                    sendDataButton.attr("disabled", "")
                    sendFileButton.attr("disabled", "")
                    switchHex.attr("disabled", "")
                    autoSend = true
                    switchAutoSend.text("stop auto send")
                    timerID = setInterval(
                        function () {
                            let value = sendDataContent.val()
                            if (!noClient && value !== "") {
                                websocket.send(JSON.stringify({
                                    "isHex": hexMode.toString(),
                                    "data": value,
                                    "event": "serverMsg",
                                    "client": currentClientName
                                }))
                            }
                            let date = new Date().toLocaleString();
                            clientMap[currentClientID]["msgList"].push({
                                "isHex": hexMode.toString(),
                                "type": "send",
                                "time": date,
                                "data": value
                            })
                            if (hexMode) {
                                history.append(`<p>【${date}】(${currentClientName}) <-send hex【${value.length}bytes】0x${value}</p><hr>`)
                            } else {
                                history.append(`<p>【${date}】(${currentClientName}) <-send【${value.length}bytes】${value}</p><hr>`)
                            }
                            let historyTmp = document.getElementById('history')
                            historyTmp.scrollTop = historyTmp.scrollHeight
                        }, parseLoopTime
                    )
                } else {
                    alert("请先设置时间和发送内容")
                }
            }
        }
    )


    window.onbeforeunload = function () {
        websocket.send("CloseTcpServer")
    }

</script>
</body>
</html>